package com.flynn.rock.jwt;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.context.SecurityContextHolderFilter;

@Configuration
public class JwtAuthenticationConfigurer extends AbstractHttpConfigurer<JwtAuthenticationConfigurer, HttpSecurity> {

    private BearerTokenResolver bearerTokenResolver;

    private JwtProcessor jwtProcessor;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        // 全局禁用 Session
        http.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
        // 创建过滤器
        JwtTokenSecurityContextHolderFilter filter = new JwtTokenSecurityContextHolderFilter();
        // 用户信息查询类
        UserDetailsService userDetailService = http.getSharedObject(ApplicationContext.class).getBean(UserDetailsService.class);
        filter.setUserDetailsService(userDetailService);
        // 令牌解析器
        BearerTokenResolver bearerTokenResolver = this.getBearerTokenResolver(http);
        filter.setBearerTokenResolver(bearerTokenResolver);
        // jwt处理器
        JwtProcessor jwtProcessor = this.getJwtProcessor(http);
        filter.setJwtProcessor(jwtProcessor);
        // 后置处理
        filter = postProcess(filter);
        // SecurityContextHolder策略
        filter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
        // 3. 添加过滤器
        http.addFilterBefore(filter, SecurityContextHolderFilter.class);
    }

    private BearerTokenResolver getBearerTokenResolver(HttpSecurity http) {
        ApplicationContext context = http.getSharedObject(ApplicationContext.class);
        if (this.bearerTokenResolver == null) {
            if (context.getBeanNamesForType(BearerTokenResolver.class).length > 0) {
                this.bearerTokenResolver = context.getBean(BearerTokenResolver.class);
            } else {
                this.bearerTokenResolver = new DefaultBearerJwtTokenResolver();
            }
        }
        return this.bearerTokenResolver;
    }

    private JwtProcessor getJwtProcessor(HttpSecurity http) {
        ApplicationContext context = http.getSharedObject(ApplicationContext.class);
        if (this.jwtProcessor == null) {
            if (context.getBeanNamesForType(JwtProcessor.class).length > 0) {
                this.jwtProcessor = context.getBean(JwtProcessor.class);
            } else {
                this.jwtProcessor = new HutoolJwtProcessor();
            }
        }
        return this.jwtProcessor;
    }
}

